/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    wm8976.c
 * @brief   wm8976芯片的相关初始化与控制操作
 * @author  K
 * @version 0.0.1
 * @date    2021-08-05
 * @license MulanPSL-1.0
 *
 * 文件修改历史：
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-08-05   | v0.0.1    | Kcode   | wm8976芯片的相关初始化与控制操作
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#include "s3c24xx.h"

extern void delay(void);

/*!
 * @brief  设置wm8976芯片的CSB引脚的电平
 * @param  [in] val  0-低电平，1-高电平
 * @return void
 */
static void set_csb(int val)
{
    if (val)
    {
        GPBDAT |= (1<<2);
    }
    else
    {
        GPBDAT &= ~(1<<2);
    }
}

/*!
 * @brief  设置wm8976芯片的CLK引脚的电平
 * @param  [in] val  0-低电平，1-高电平
 * @return void
 */
static void set_clk(int val)
{
    if (val)
    {
        GPBDAT |= (1<<4);
    }
    else
    {
        GPBDAT &= ~(1<<4);
    }
}

/*!
 * @brief  设置wm8976芯片的DAT引脚的电平
 * @param  [in] val  0-低电平，1-高电平
 * @return void
 */
static void set_dat(int val)
{
    if (val)
    {
        GPBDAT |= (1<<3);
    }
    else
    {
        GPBDAT &= ~(1<<3);
    }
}

/*!
 * @brief  wm8976芯片写寄存器
 * @param  [in] reg  所要写的寄存器的地址
 * @param  [in] data 所要写的数据 
 * @return void
 */
static void wm8976_write_reg(unsigned char reg, unsigned int data)
{
	int i;

    /* wm8976传输的是16位数据 = 高七位表示寄存器地 + 低9位表示寄存器的值 */
	unsigned short val = (reg << 9) | (data & 0x1ff);

    set_csb(1);
    set_dat(1);
    set_clk(1);

    /*!
     * 把16位val值写入wm8976，从高位开始传输
     * 先让时钟变为低电平，然后时钟变为高电平，一个周期传输一位
     * 传输一位完毕后，移动到下一位
     */
	for (i = 0; i < 16; i++){
		if (val & (1<<15))
		{
            set_clk(0);
            set_dat(1);
			delay();
            set_clk(1);
		}
		else
		{
            set_clk(0);
            set_dat(0);
			delay();
            set_clk(1);
		}

		val = val << 1;
	}

    /*! 
     * 传输16位完成后，让csb信号产生低脉冲，写入wm8976
     */
    set_csb(0);
    delay();

    /*!
     * 引脚恢复到高电平状态
     */
    set_csb(1);
    set_dat(1);
    set_clk(1);	
}

/*!
 * @brief  通过控制接口(GPB2,3,4)读写寄存器进行初始化
 * @return void
 */ 
void wm8976_init(void)
{
    /*!
     * 先软复位
     */
	wm8976_write_reg(0, 0);

	/*!
	 * OUT2的左/右声道打开
	 * 左/右通道输出混音打开
	 * 左/右DAC打开
	 */
	wm8976_write_reg(0x3, 0x6f);
	
	wm8976_write_reg(0x1, 0x1f);    //biasen,BUFIOEN.VMIDSEL=11b  
	wm8976_write_reg(0x2, 0x185);   //ROUT1EN LOUT1EN, inpu PGA enable ,ADC enable

	wm8976_write_reg(0x6, 0x0);     //SYSCLK=MCLK  
	wm8976_write_reg(0x4, 0x10);    //16bit 		
	wm8976_write_reg(0x2B,0x10);    //BTL OUTPUT  
	wm8976_write_reg(0x9, 0x50);    //Jack detect enable  
	wm8976_write_reg(0xD, 0x21);    //Jack detect  
	wm8976_write_reg(0x7, 0x01);    //Jack detect 
}

/*!
 * @brief  wdm8976芯片设置音量大小
 * @param[in] volume 音量值，范围：0~100，0-最小音量，100-最大音量
 * @return void
 */
void wm8976_set_volume(int volume)
{
    /*!
     * 对于uda1341，其音量值范围：0~60
     * 0-最小音量，60-最大音量
     * WM8976: 52(左通道),53(右通道)号寄存器bit[5:0]表示音量
     */
    int val = volume * 63 / 100;
    wm8976_write_reg(52, (1 << 8) | val);
    wm8976_write_reg(53, (1 << 8) | val);
}